#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__all__ = []

from .. import formlib as layout
from .. import pilelib as stack
from .. import stackfill as fill
from ..forms import canfield as CanfieldLayout
from ..gamelib import state, info as gi, game
from ..hint import CautiousDefaultHint
from ..packlib import info as cs, place
from ..utillib.misc import kwdefault

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class Hint(CautiousDefaultHint):

    def score_move_waste(self, from_stack, to_stack, pile, rpile):
        self.score_move_pile(from_stack, to_stack, pile, rpile)
        # we prefer moving cards from the waste over everything else
        self._score += 100000


class PlayMethod(object):
    """
    a Canfield row stack only accepts a full other row stack
    (cannot move part of a sequence from row to row)
    """

    def _play_sequence(self, cards):
        """
        _build_sequence(cards:tup) -> bool

        :param tuple cards: cards to move from this pile
        :return: cards moveable?
        :rtype: boolean
        """
        return len(cards) in (1, len(self.cards))


class CanfieldRush_Talon(stack.WasteTalon):

    def deal_cards(self, sound=False):
        """
        can_deal_cards() -> bool

        Check by Game.talon_deal() if pile can deal more cards. Default is
        while there are cards available. Reset number dealt to 4 - rounds.

        :return: deal more cards?
        :rtype: True | False
        """
        self.num_deal = 4 - self.round
        super(CanfieldRush_Talon, self).deal_cards(sound=sound)


class Canfield_AC_RowStack(PlayMethod, stack.AC_RowStack):
    pass


class Canfield_SS_RowStack(PlayMethod, stack.SS_RowStack):
    pass


class Canfield_RK_RowStack(PlayMethod, stack.RK_RowStack):
    pass


class EagleWing_ReserveStack(stack.OpenStack):

    def cardFlips(self):
        """
        cardFlips() -> bool

        Check if pile can flip face down top card. Check parent cardFlips()
        and pile has one card left.

        :return: pile flips top card?
        :rtype: boolean
        """
        if not super(EagleWing_ReserveStack, self).cardFlips():
            return False
        return len(self.cards) == 1


class SuperiorCanfield(game.Game):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all.

    _reserve_
      Init deal 13 open card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Layout _layout_: layout.CanfieldLayout
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=101, name='Superior Canfield', game_type=GT.CANFIELD,
                    decks=1, redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _layout_ = CanfieldLayout.CanfieldLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=cs.INFINITE,
                           num_deal=3)
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.Vary_SS_Foundation, max_move=0)
    _row_ = Wrap(Canfield_AC_RowStack, mod=13)
    _reserve_ = stack.OpenStack
    _hint_ = Hint

    def _create_game(self, **kw):
        kwdefault(kw, rows=4, holdcards=13)
        l, s = super(SuperiorCanfield, self)._create_game(**kw), self.s
        self['texts'].info = l.create_info_text(s['foundations'][-1],
                                      'se' if kw['rows'] > l.NSUITS else 'ss')
        return l

    def _start(self, reserves=13, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps.
          - s[rows] 1 ea.
          - s[reserves] 13 ea up.

        .. \_start([reserves=13, flip=True]) -> None
        """
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip, frames=4)
        self.s['talon'].dealRow(rows=self.s['reserves'], frames=4)
        self.s['talon'].dealRow(reverse=True)

    @state.not_state('is_preview')
    def _update_text(self):
        if not self.texts['info']:
            return
        base_rank = self.s['foundations'][0].cap['base_rank']
        t = '' if base_rank == cs.ANY else self._RANKS_.get(base_rank,
                                                         base_rank + 1)
        self.texts['info'].config(text=t)


class Skippy(SuperiorCanfield):
    """
    Finish cards on _foundation without limit turn.

    _row_
      Pile 16 over 4 row S _foundation_. Init deal 4 card. Build down in rank
      alone wrap. Play top. Base rank less _foundation_ base rank.

    _reserve_
      Pile 1 S _talon_. Build any 1 card. Play top.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 N. Init deal 1 base card. Build up in rank by same suit wrap.
      Play top.
    ------
    :cvar Layout _layout_: layout.SkippyLayout
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation
    :cvar Stack _row_: stack.RK_RowStack (max_move=1, mod=13)
    :cvar Stack _reserve_: stack.ReserveStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=605, name='Skippy', game_type=GT.FAN_TYPE, decks=2,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _foundation_ = stack.Vary_SS_Foundation
    _row_ = Wrap(stack.RK_RowStack, max_move=1, mod=13)
    _reserve_ = stack.ReserveStack

    def _create_game(self, playcards=8, **kw):
        kwdefault(kw, rows=16, playcards=8, ncols=4, reserves=4)
        return super(Skippy, self)._create_game(self, **kw)

    def _start(self, rows=4, flip=False, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps.
          - s[rows] 4 ea top. save all caps foundation - 1 % 13

        .. \_start([rows=4, flip=False]) -> None
        """
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(self.s['foundations'], base_rank=base_rank)
        self._save_stack_caps(self.s['rows'], base_rank=(base_rank - 1) % 13)
        for i in range(rows - 1):
            self.s['talon'].dealRow(flip=flip, frames=0)
        self.s['talon'].dealRow()


class Canfield(SuperiorCanfield):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=105, name='Canfield', game_type=(GT.CANFIELD |
                    GT.CONTRIB | GT.POPULAR | GT.GNOME | GT.XPAT), decks=1,
                    redeals=cs.INFINITE, version='2.02', skill_level=SL.BALANCED)
    __author__ = 'Drew Csillag'
    __version__ = 7.70

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps.
          - s[rows] 1 ea.
          - s[reserves] 13 ea top.

        .. \_start([reserves=13, flip=False]) -> None
        """
        kw.setdefault('flip', False)
        super(Canfield, self)._start(**kw)

    @state.move_state('fill')
    def _auto_fill(self, stack):
        fill.fromReserve(self, stack, self.s['rows'])


class DoubleCanfield(Canfield):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [5 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [8 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=106, name='Double Canfield', game_type=GT.CANFIELD,
                    decks=2, redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    altnames=('Canfield (2 Decks)',), version='2.90')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 5)
        return super(DoubleCanfield, self)._create_game(self, **kw)


class TripleCanfield(Canfield):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [12 over 2 row N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 26 card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same
      suit wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=396, name='Triple Canfield', game_type=GT.CANFIELD,
                    decks=3, redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    altnames=('Canfield (3 Decks)',), version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, holdcards=26, rows=7)
        return super(TripleCanfield, self)._create_game(self, **kw)

    def _start(self, reserves=26, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base. save all caps.
          - s[rows] 1 ea.
          - s[reserves] 26 ea top.

        .. \_start([reserves=13, flip=False]) -> None
        """
        return super(TripleCanfield, self)._start(reserves=reserves, **kw)


class Rainfall(Canfield):
    """
    Finish cards on _foundation within 3 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init 1 deal base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=99, name='Rainfall', game_type=(GT.CANFIELD |
                    GT.ORIGINAL), decks=1, redeals=2, skill_level=SL.BALANCED,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)


class Rainbow(Canfield):
    """
    Finish cards on _foundation within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank alone
      wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_RK_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=108, name='Rainbow', game_type=GT.CANFIELD, decks=1,
                    skill_level=SL.BALANCED, version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _row_ = Wrap(Canfield_RK_RowStack, mod=13)


class Storehouse(Rainfall):
    """
    Finish cards on _foundation within 3 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by same
      suit wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base TWO. Build up in rank by same suit wrap. Play
      none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_SS_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=100, name='Storehouse', game_type=(GT.CANFIELD |
                   GT.GNOME), decks=1, redeals=2, skill_level=SL.BALANCED,
                   altnames=('Provisions', 'Straight Up', 'Thirteen Up'),
                   version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = Wrap(Canfield_SS_RowStack, mod=13)

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return TWO on top by rank, suit, deck for _foundation_ deal.
        """
        return place.MoveToTop(cards, place.AllTwo)

    def _start(self, reserves=13, flip=False, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea.
          - s[reserves] 13 ea top.
          - s[rows] 1 ea.

        .. \_start([reserves=13, flip=False]) -> None
        """
        self.s['talon'].dealRow(rows=self.s['foundations'])
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip,
                                    frames=0)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow(reverse=True)

    @state.not_state('is_preview')
    def _update_text(self):
        pass


class VariegatedCanfield(Storehouse):
    """
    Finish cards on _foundation within 3 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [5 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 open card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal base ACE. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3, num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=102, name='Variegated Canfield', game_type=GT.CANFIELD,
                    decks=2, redeals=2, skill_level=SL.BALANCED,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=3, num_deal=3)
    _row_ = Canfield_AC_RowStack

    def _create_game(self, **kw):
        kw.setdefault('rows', 5)
        l = super(Rainfall, self)._create_game(self, **kw)
        self.texts['info'] = None
        return l

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE on top by rank, suit, deck for _foundation_ deal.
        """
        return place.MoveToTop(cards, place.AllAce)

    def _start(self, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea.
          - s[reserves] 13 ea top.
          - s[rows] 1 ea.

        .. \_start([reserves=13, flip=True]) -> None
        """
        return super(VariegatedCanfield, self)._start(flip=flip, **kw)


class Acme(Storehouse):
    """
    Finish cards on _foundation within 2 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by same
      suit. Play top. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base ACE. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=2)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.SS_RowStack (max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=403, name='Acme', game_type=GT.CANFIELD, decks=1,
                    redeals=1, skill_level=SL.BALANCED, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _foundation_ = stack.SS_Foundation
    _row_ = Wrap(stack.SS_RowStack, max_move=1)
    _hint_ = Hint

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return ACE on top by rank, suit, deck for _foundation_ deal.
        """
        return place.MoveToTop(cards, place.AllAce)

    def _start(self, reserves=13, flip=False, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea.
          - s[reserves] 13 ea top.
          - s[rows] 1 ea.

        .. \_start([reserves=13, flip=False]) -> None
        """
        self.s['talon'].dealRow(rows=self.s['foundations'], frames=0)
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow(reverse=True)


class Chameleon(Rainbow):
    """
    Finish cards on _foundation within 3 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [3 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank alone
      wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 12 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base TWO. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_RK_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=43, name='Chameleon', game_type=(GT.CANFIELD |
                    GT.GNOME), decks=1, skill_level=SL.BALANCED,
                    altnames=('Kansas',), version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, holdcards=12, rows=3)
        return super(Chameleon, self)._create_game(self, **kw)

    def _start(self, reserves=12, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 base.
          - s[reserves] 12 ea top.
          - s[rows] 1 ea.

        .. \_start([reserves=12, flip=False]) -> None
        """
        kw.setdefault('reserves', 12)
        super(Chameleon, self)._start(reserves=reserves, **kw)


class AmericanToad(Canfield):
    """
    Finish cards on _foundation within 2 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [8 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by same
      suit wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 20 open card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=2, num_deal=3)
    :cvar Stack _talon_: stack.WasteStack (max_rounds=2)
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_SS_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=103, name='American Toad', game_type=GT.CANFIELD,
                    decks=2, redeals=1, skill_level=SL.BALANCED,
                    version='3.00')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _row_ = Wrap(Canfield_SS_RowStack, mod=13)

    def _create_game(self, **kw):
        kwdefault(kw, holdcards=20, rows=8)
        return super(AmericanToad, self)._create_game(self, **kw)

    def _start(self, reserves=20, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea.
          - s[reserves] 20 ea up.
          - s[rows] 1 ea.

        .. \_start([reserves=20, flip=True]) -> None
        """
        return super(AmericanToad, self)._start(reserves=reserves, flip=flip,
                                                **kw)


class Demon(Canfield):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Pile 8 horz S _foundation_. Init deal 1 card. Build down in rank by alt
      color wrap. Play seq. Gap deal 1 card from _reserve_

    _reserve_
      Pile 1 S _talon_. Init deal 40 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal 3 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 3 card. Build none. Play top.

    _foundation_
      Pile 8 N. Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=476, name='Demon', game_type=GT.CANFIELD, decks=2,
                    redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(stack.AC_RowStack, mod=13)

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, holdcards=40)
        return super(Demon, self)._create_game(**kw)

    def _start(self, reserves=40, **kw):
        """
        Deal initial cards for new game.
          - s[foundations] 1 ea.
          - s[reserves] 40 ea top.
          - s[rows] 1 ea.

        .. \_start([reserves=40, flip=False]) -> None
        """
        return super(Demon, self)._create_game(reserves=reserves, **kw)


class CanfieldRush(Canfield):
    """
    Finish cards on _foundation within 3 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play top or all. Gap deal 1 card from _reserve_

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_. Each turn 1 more card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal 1 base card. Build up in rank by same suit wrap.
      Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=521, name='Canfield Rush', game_type=GT.CANFIELD,
                    decks=1, redeals=2, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(CanfieldRush_Talon, max_rounds=3, num_deals=3)


class Minerva(SuperiorCanfield):
    """
    Finish cards on _foundation within 2 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 4 alt open card. Build down in
      rank by alt color. Play seq. Base KING.

    _reserve_
      Init deal 11 open card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=2)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack (base_rank=KING)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=422, name='Minerva', game_type=GT.CANFIELD, decks=1,
                    redeals=1, skill_level=SL.BALANCED, version='0.91fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _row_ = Wrap(stack.AC_RowStack, base_rank=cs.KING)

    def _create_game(self, **kw):
        kwdefault(kw, rows=7, holdcards=11)
        l = super(Minerva, self)._create_game(**kw)
        self.game.texts['info'] = None
        return l

    def _start(self, reserves=11, flip=False, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 4 ea alt.
          - s[reserves] 11 ea top.

        .. \_start([reserves=11, flip=False]) -> None
        """
        for flip in (False, True, False):
            self.s['talon'].dealRow(frames=0, flip=flip)
        self.s['talon'].dealRow()
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip)
        self.s['talon'].dealRow(rows=self.s['reserves'])


class Munger(Minerva):
    """
    Finish cards on _foundation within 1 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 4 alt open card. Build down in
      rank by alt color. Play seq. Base KING.

    _reserve_
      Init deal 11 open card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=1)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack (base_rank=KING)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=360, name='Munger', game_type=GT.CANFIELD, decks=1,
                    skill_level=SL.BALANCED, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=1)

    def _create_game(self, **kw):
        kw.setdefault('holdcards', 7)
        return super(Munger, self)._create_game(self, **kw)

    def _start(self, reserves=7, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 4 ea alt.
          - s[reserves] 7 ea top.

        .. \_start([reserves=7, flip=False]) -> None
        """
        return super(Munger, self)._start(self, reserves=reserves, **kw)


class Mystique(Munger):
    """
    Finish cards on _foundation within 2 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 4 alt open card. Build down in
      rank by alt color. Play seq.

    _reserve_
      Init deal 9 open card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=2)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=494, name='Mystique', game_type=GT.CANFIELD, decks=1,
                    skill_level=SL.BALANCED, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = stack.AC_RowStack

    def _create_game(self, **kw):
        kw.setdefault('holdcards', 9)
        return super(Mystique, self)._create_game(self, **kw)

    def _start(self, reserves=9, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 4 ea alt.
          - s[reserves] 9 ea top.

        .. \_start([reserves=11, flip=False]) -> None
        """
        return super(Mystique, self)._start(self, reserves=reserves, **kw)


class EagleWing(Canfield):
    """
    Finish cards on _foundation within 3 turn.

    _row_
      Pile 8 horz S _foundation_. Init deal 1 card. Build down in rank by same
      suit wrap. Play top. Max 3 cards. Gap deal 1 card from _reserve_

    _reserve_
      Pile 1 center _row_. Init deal 13 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 N. Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Canfield_AC_RowStack (mod=13, max_move=1, max_cards=3)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=112, name='Eagle Wing', game_type=(GT.CANFIELD |
                    GT.GNOME), decks=1, redeals=2, skill_level=SL.BALANCED,
                    version='3.10')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _row_ = Wrap(stack.SS_RowStack, mod=13, max_move=1, max_cards=3)
    _reserve_ = EagleWing_ReserveStack

    def _create_game(self, **kw):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 9 * l.XS + l.XM, l.YM + 4 * l.YS,)
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        l.set_rounds_text(s['talon'], 'sss', dx=l.XS)
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 's')
        x = self.width - l.NSUITS * l.XS
        for (x, y), suit in zip(self.col_block_iter(x, y, npiles=l.NSUITS,
                                                    ncols=l.NSUITS), l.SUITS):
            s['foundations'].append(self._foundation_(x, y, game=self,
                                                   suit=suit))
        self.game.texts['info'] = l.create_info_text(s['foundations'][-1], 'se')
        x = l.XM
        for dx, dy in zip(range(9), (2, 4, 6, 4, 2, 4, 6, 4, 2)):  # Horz wave
            x, y = l.delta_coords(y=y + l.YS, dx=dx, dy=dy, fy=10)
            if dx == 4:  # Center
                s['reserves'].append(self._reserve_(x, y, game=self))
            else:  # Outer
                s['rows'].append(self._row_(x, y, game=self))
        l.set_ncards_text(s['reserves'][-1], 's')
        l.defaultStackGroups()
        return l


class Doorway(game.Game):
    """
    Finish cards on _foundation within 1 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.DoorwayLayout
        - row [5 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 W, 1 E row, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank alone.
      Play top.

    _reserve_
      Build 1 card. W base KING. E base QUEEN. Play
      top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.RK_RowStack (max_move=1)
    :cvar Stack _reserve_: stack.ReserveStack (base_rank=KING),
        stack.ReserveStack (base_rank=QUEEN)
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=527, name='Doorway', game_type=GT.KLONDIKE, decks=1,
                    skill_level=SL.BALANCED, version='0.93fc',
                    altnames=('Solstice',))
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = CanfieldLayout.DoorwayLayout
    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = stack.SS_Foundation
    _row_ = Wrap(stack.RK_RowStack, max_move=1)
    _reserves_ = (Wrap(stack.ReserveStack, base_rank=cs.KING),
                  Wrap(stack.ReserveStack, base_rank=cs.QUEEN),)
    _hint_ = CautiousDefaultHint

    def _create_game(self, **kw):
        kw.setdefault('rows', 5)
        l = super(Doorway, self)._create_game(self, rows=5)
        for reserve in self.s['reserves']:
            base_rank = reserve.caps['base_rank']
            if base_rank != cs.ANY:
                l.set_misc_text(reserve, anchor='s',
                                text=self.RANKS[base_rank])
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealRow()


class Gate(Doorway):
    """
    Finish cards on _foundation within 1 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.DoorwayLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 W, 1 E row, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by alt
      color. Play seq. Gap deal 1 card from _reserve_, else _waste_.

    _reserve_
      Init deal 6 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.

    seealso::
      http://en.wikipedia.org/wiki/Gate_%28solitaire%29
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack * 2
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=315, name='Gate', game_type=GT.CANFIELD, decks=1,
                    skill_level=SL.BALANCED, version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = stack.AC_RowStack
    _reserves_ = (stack.OpenStack,) * 2

    def _create_game(self, rows=8, **kw):
        kwdefault(kw, rows=8, texts=True)

    def _start(self, reserves=6, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 6 ea up.
          - s[rows] 1 ea.

        .. \_start([reserves=6, flip=True]) -> None
        """
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip, frames=0)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow()

    @state.move_state('fill')
    def _auto_fill(self, stack):
        fill.fromReserveOrWaste(self, stack, self.s['rows'])


class LittleGate(Gate):
    """
    Finish cards on _foundation within 1 turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.DoorwayLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 W, 1 E row, no offset]
        - foundation [4 horz N, no offset]


    _row_
      Init deal 1 card. Build down in rank by alt
      color. Play seq. Gap deal 1 card from _reserve_, else _waste_.

    _reserve_
      Init deal 6 card. Build none. Play top.

    _talon_
      Deal 1 card on _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Init deal base card. Build up in rank by same suit. Play none.

    seealso::
      http://en.wikipedia.org/wiki/Gate_%28solitaire%29
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack * 2
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=316, name='Little Gate', game_type=GT.CANFIELD,
                    decks=1, skill_level=SL.BALANCED,
                    version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 4)
        return super(LittleGate, self)._create_game(self, **kw)


class Duke(game.Game):
    """
    Finish cards on _foundation within 3 turn.

    _row_
      Pile 4 horz S _foundation_. Init deal 1 card. Build down in rank by alt
      color. Play seq.

    _reserve_
      Pile 4 over 2 col E. Init deal 3 card. Build none. Play top.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 4 N. Build up in rank by same suit. Play top.
    ------
    :cvar Layout _layout_: layout.DukeLayout
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.DefaultHint
    """
    __info__ = dict(id=413, name='Duke', game_type=GT.CANFIELD, decks=1,
                    redeals=2, skill_level=SL.BALANCED, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = layout.DukeLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=3)
    _waste_ = stack.WasteStack
    _foundation_ = stack.SS_Foundation
    _row_ = stack.AC_RowStack
    _reserve_ = stack.OpenStack

    def _create_game(self, **kw):
        kwdefault(kw, rows=4, reserves=4, ncols=3, playcards=12)
        return super(Duke, self)._create_game(self, **kw)

    def _start(self, reserves=3, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 3 ea up.
          - s[rows] 1 ea.

        .. \_start([reserves=3, flip=True]) -> None
        """
        for i in range(reserves):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip, frames=0)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow()


class Lafayette(Canfield):
    """
    Finish cards on _foundation without limit turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.canfield.CanfieldLayout
        - row [4 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - reserve [1 S talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 1 card. Build down in rank by alt
      color wrap. Play seq. Gap deal 1 card from _reserve_. Base SEVEN.

    _reserve_
      Init deal 13 card. Build none. Play top.

    _talon_
      Deal 3 card on _waste_.

    _waste_
      Init deal 3 card. Build none. Play top.

    _foundation_
      Build in rank by same suit. W Up. E Down. Play top.
    ------
    :cvar Stack _talon_: stack.WasteTalon (max_rounds=INFINITE,
      num_deal=3)
    :cvar Stack _talon_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: stack.AC_RowStack (base_rank=SEVEN)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: Hint
    """
    __info__ = dict(id=642, name='Lafayette', game_type=GT.CANFIELD,
                    decks=1, redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundations_ = (stack.SS_Foundation,
                     Wrap(stack.SS_Foundation, base_rank=cs.KING,
                                  dir=-1),)
    _row_ = Wrap(stack.AC_RowStack, base_rank=cs.SEVEN)

    def _create_game(self, **kw):
        l = layout.Layout(self)
        kwdefault(kw, bases=l.SUITS * 2, reserves=4)
        return super(Duke, self)._create_game(self, **kw)

    def _start(self, reserves=13, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 13 ea up.
          - s[rows] 1 ea.

        .. \_start([reserves=13, flip=True]) -> None
        """
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=flip,
                                    frames=0)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow()


PROVIDES = [Canfield, SuperiorCanfield, Rainfall, Rainbow, Storehouse,
            Chameleon, DoubleCanfield, AmericanToad, VariegatedCanfield,
            EagleWing, Gate, LittleGate, Munger, TripleCanfield, Acme, Duke,
            Minerva, Demon, Mystique, CanfieldRush, Doorway, Skippy,
            Lafayette]